# 方法1  通过 __new__方法控制实例化 推荐
class Singleton:
    _instance = None  # 类属性保存唯一实例

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            # 首次创建实例时调用基类的 __new__
            cls._instance = super().__new__(cls)
        return cls._instance  # 始终返回同一个实例

    def __init__(self, config):
        # 防止重复初始化
        if not hasattr(self, '_initialized'):
            self.config = config
            self._instance = True


# 使用示例
s1 = Singleton(config='DB_config')
s2 = Singleton(config='New_config')
print(s1 is s2)
print(s1.config)


# print(id(s1) == id(s2))


# 方法2 装饰器

def singleton(cls):
    instances = {}

    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]

    return get_instance


@singleton
class Logger:
    def __init__(self, log_file):
        self.log_file = log_file


logger1 = Logger('app.log')
logger2 = Logger('new.log')
print(logger1 is logger2)
print(logger1.log_file)


# 方法3 通过元类
class SingletonMeta(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super().__call__(*args, **kwargs)
        return cls._instances[cls]


class DatabaseConnection(metaclass=SingletonMeta):
    def __init__(self, connection_string):
        self.conn = self._connect(connection_string)

    def _connect(self, conn_str):
        print(f'Connecting to {conn_str}...')
        return 'Connection object'


# 使用示例
db1 = DatabaseConnection("mysql://user:pwd@localhost")
db2 = DatabaseConnection("postgres://user:pwd@localhost")
print(db1 is db2)  # 输出: True
print(db1.conn)  # 输出: "Connection Object"

